package gs.es.plugin.safe;

import com.alibaba.fastjson.JSON;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.rest.*;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by eviltuzki on 17-1-19.
 */
public class SafeFilter extends RestFilter {
    private static ESLogger logger = ESLoggerFactory.getLogger("Safe Plugin");
    @Override
    public void process(RestRequest restRequest, RestChannel restChannel, RestFilterChain restFilterChain) {
        boolean isContinue;
        if (DataStore.isOpen()) {
            isContinue=SizeFilter(restRequest.content().toUtf8(),restChannel);
            if (!isContinue){
                return;
            }else {
                isContinue=DeleteAndAccessFilter(restRequest,restChannel, restFilterChain);
            }
        } else {
            restFilterChain.continueProcessing(restRequest, restChannel);    //不开启插件则直接放行
        }
    }
    public String Standardize(String old) {
        Pattern pattern = Pattern.compile("\"");
        Matcher m = pattern.matcher(old);
        return m.replaceAll("'");
    }
    /**
     * from size 过滤器
     * @param str 获取请求的文本
     * @param restChannel
     * @return 是否可以继续
     */
    private boolean SizeFilter(String str,RestChannel restChannel){
        String s = Standardize(str);
        EsRequest object = null;
        try {
            object = JSON.parseObject(s, EsRequest.class);
        } catch (Exception e) {
            return true;
        }
        if (object != null&&(object.getFrom()> DataStore.getFrom()||object.getSize()>DataStore.getSize())) {
            BytesRestResponse res = new BytesRestResponse(RestStatus.FORBIDDEN, "Size Or From Is Too Large, Forbidden By Safe Plugin.");//拦截
            restChannel.sendResponse(res);
            return false;
        }
        return true;
    }
    /**
     *  Delete 方法过滤器
     * @param restRequest
     * @param restChannel
     * @param restFilterChain
     * @return 是否可以继续使用过滤器，如果返回false 直接return方法
     */
    private boolean DeleteAndAccessFilter(RestRequest restRequest, RestChannel restChannel, RestFilterChain restFilterChain) {
        boolean isLocal;
        String remote = restRequest.getRemoteAddress().toString();
        remote = remote.substring(1, remote.indexOf(':'));
        if (DataStore.getWhiteList().size() == 0) {        //白名单为空，则只能本机进行删除操作
            String local = restRequest.getLocalAddress().toString();
            local = local.substring(1, local.indexOf(':'));
            isLocal = remote.equals(local); //是否是本机判断
        } else { //白名单不为空
            isLocal = DataStore.getWhiteList().contains(remote); //判断是否在白名单中
        }
        if (DataStore.isAccess()){
            if (isLocal) {
                restFilterChain.continueProcessing(restRequest, restChannel);//Ip是本机或者在白名单中放行
            } else {
                logger.warn("IP:" + remote + " Try to Access and failed");
                BytesRestResponse res = new BytesRestResponse(RestStatus.FORBIDDEN, "Forbidden Method Request by Safe plugin");//拦截
                restChannel.sendResponse(res);
            }
            return false;//当开启访问验证后，其优先级最高，不再进行删除验证
        }
        if (DataStore.isDelete()){
            RestRequest.Method method = restRequest.method();   //请求的方法是不是Delete方法
            if (method.equals(RestRequest.Method.DELETE)) {
                if (isLocal) {
                    restFilterChain.continueProcessing(restRequest, restChannel);//Ip是本机或者在白名单中放行
                } else {
                    logger.warn("IP:" + remote + " Try to Delete and failed");
                    BytesRestResponse res = new BytesRestResponse(RestStatus.FORBIDDEN, "Forbidden Method Request by Safe plugin");//拦截
                    restChannel.sendResponse(res);
                }
            } else {
                restFilterChain.continueProcessing(restRequest, restChannel);    //非Delete方法直接放行
            }
            return false;//验证删除
        }

        return false;//如果两者都未进行配置
    }
}
